﻿using System;
using System.Text;

namespace GPS.GPSLanguage
{
    class GPSData
    {
        private bool _Complete;
        private TimeSpan _TimeTaken;
        private MessageType _MessageType;
        private int _LatitudeDegrees;
        private double _LatitudeMinutes;
        private DirectionType _LatitudeDirection;
        private int _LongitudeDegrees;
        private double _LongitudeMinutes;
        private DirectionType _LongitudeDirection;
        private GGAQualityType _GGAQualityType;
        private int _SatelliteCount;
        private double _HorizontalDilution;
        private double _VerticalDilution;
        private double _Altitude;
        private UnitType _AltitudeUnitType;
        private double _HeightOfGeoId;
        private UnitType _HeightOfGeoIdUnitType;
        private TimeSpan _LastDGPSUpdate;
        private int _DGPSStationID;
        private StatusType _RMCStatus;
        private double _Speed;
        private double _TrackAngle;
        private DateTime _DateTaken;
        private double _MagneticVariation;
        private DirectionType _MagneticDirection;
        private SelectionMode _SelectionMode;
        private int _threeDFix;
        private int[] _PRNForFix;
        private int[] _Elevation;
        private int[] _Azimuth;
        private int[] _SNR;
        private double _DilutionOfPrecision;
        private double _LatitudeDecimalDegrees;
        private double _LongitudeDecimalDegrees;
        public int CurrentSatelliteCount;
        private int _SentenceCount;
        private int _SentenceNumber;

        public GPSData()
        {
            Init();
        }

        void Init()
        {
            _Complete = false;
            _SatelliteCount = 0;
            _PRNForFix = new int[12]; // default for GPGSA
            _Elevation = null;
            _Azimuth = null;
            _SNR = null;
            CurrentSatelliteCount = 0;
            _SentenceCount = 0;
            _SentenceNumber = 0;
        }

        public bool Complete
        {
            get { return _Complete; }
        }

        public MessageType MessageType
        {
            get { return _MessageType; }
        }

        public TimeSpan TimeTaken
        {
            get { return _TimeTaken; }
        }

        public double LatitudeDecimalDegrees
        {
            get { return _LatitudeDecimalDegrees; }
        }

        public int LatitudeDegrees
        {
            get { return _LatitudeDegrees; }
        }

        public double LatitudeMinutes
        {
            get { return _LatitudeMinutes; }
        }

        public DirectionType LatitudeDirection
        {
            get { return _LatitudeDirection; }
        }

        public double LongitudeDecimalDegrees
        {
            get { return _LongitudeDecimalDegrees; }
        }

        public int LongitudeDegrees
        {
            get { return _LongitudeDegrees; }
        }

        public double LongitudeMinutes
        {
            get { return _LongitudeMinutes; }
        }

        public DirectionType LongitudeDirection
        {
            get { return _LongitudeDirection; }
        }

        public GGAQualityType GGAQualityType
        {
            get { return _GGAQualityType; }
        }

        public int SatelliteCount
        {
            get { return _SatelliteCount; }
        }

        public double HorizontalDilution
        {
            get { return _HorizontalDilution; }
        }

        public double VerticalDilution
        {
            get { return _VerticalDilution; }
        }

        public double DilutionOfPrecision
        {
            get { return _DilutionOfPrecision; }
        }

        public double Altitude
        {
            get { return _Altitude; }
        }

        public UnitType AltitudeUnitType
        {
            get { return _AltitudeUnitType; }
        }

        public double HeightOfGeoId
        {
            get { return _HeightOfGeoId; }
        }

        public UnitType HeightOfGeoIdUnitType
        {
            get { return _HeightOfGeoIdUnitType; }
        }

        public TimeSpan LastDGPSUpdate
        {
            get { return _LastDGPSUpdate; }
        }

        public int DGPSStationID
        {
            get { return _DGPSStationID; }
        }

        public StatusType RMCStatus
        {
            get { return _RMCStatus; }
        }

        public double Speed
        {
            get { return _Speed; }
        }

        public double TrackAngle
        {
            get { return _TrackAngle; }
        }

        public DateTime DateTaken
        {
            get { return _DateTaken; }
        }

        public double MagneticVariation
        {
            get { return _MagneticVariation; }
        }

        public DirectionType MagneticDirection
        {
            get { return _MagneticDirection; }
        }

        public SelectionMode SelectionMode
        {
            get { return _SelectionMode; }
        }

        public int ThreeDFix
        {
            get { return _threeDFix; }
        }

        public int PRNForFix(int idx)
        {
            return _PRNForFix[idx];
        }

        public int SatelliteElevation(int idx)
        {
            return _Elevation[idx];
        }

        public int SatelliteAzimuth(int idx)
        {
            return _Azimuth[idx];
        }

        public int SatelliteSNR(int idx)
        {
            return _SNR[idx];
        }

        public int SentenceCount
        {
            get { return _SentenceCount; }
        }

        public int SentenceNumber
        {
            get { return _SentenceNumber; }
        }

        internal void SetMessageType(MessageType messageType)
        {
            _MessageType = messageType;
        }

        internal void SetTimeTaken(TimeSpan timeTaken)
        {
            _TimeTaken = timeTaken;
        }

        internal void SetLatitude(int degrees, double minutes, DirectionType dir)
        {
            _LatitudeDegrees = degrees;
            _LatitudeMinutes = minutes;
            _LatitudeDirection = dir;

            double latDeg = degrees * 1000000.0;
            double latMin = minutes * 1000000.0;
            _LatitudeDecimalDegrees = (latDeg + (latMin / 60.0)) / 1000000.0;
            if (dir == DirectionType.South) // It's a negative value
                _LatitudeDecimalDegrees *= -1;
        }

        internal void SetLongitude(int degrees, double minutes, DirectionType dir)
        {
            _LongitudeDegrees = degrees;
            _LongitudeMinutes = minutes;
            _LongitudeDirection = dir;

            double lonDeg = degrees * 1000000.0;
            double lonMin = minutes * 1000000.0;
            _LongitudeDecimalDegrees = (lonDeg + (lonMin / 60.0)) / 1000000.0;
            if (dir == DirectionType.West) // It's a negative value
                _LongitudeDecimalDegrees *= -1;
        }


        internal void SetQualityToken(GGAQualityType val)
        {
            _GGAQualityType = val;
        }

        internal void SetSatelliteCount(int satCount)
        {
            _SatelliteCount = satCount;
            _PRNForFix = new int[satCount];
            _Elevation = new int[satCount]; ;
            _Azimuth = new int[satCount]; ;
            _SNR = new int[satCount]; ;
        }

        internal void SetHorizontalDilution(double val)
        {
            _HorizontalDilution = val;
        }

        internal void SetAltitudeAndUnitType(double val, UnitType unitType)
        {
            _Altitude = val;
            _AltitudeUnitType = unitType;
        }

        internal void SetHeightOfGeoIdAndUnitType(double val, UnitType unitType)
        {
            _HeightOfGeoId = val;
            _HeightOfGeoIdUnitType = unitType;
        }

        internal void SetLastDGPSUpdate(TimeSpan ts)
        {
            _LastDGPSUpdate = ts;
        }

        internal void SetDGPSStationID(int stationID)
        {
            _DGPSStationID = stationID;
        }

        internal void SetGPSSentenceComplete()
        {
            _Complete = true;
        }

        internal void SetRMCStatus(StatusType rMCStatus)
        {
            _RMCStatus = rMCStatus;
        }

        internal void SetSpeed(double val)
        {
            _Speed = val;
        }

        internal void SetTrackAngle(double val)
        {
            _TrackAngle = val;
        }

        internal void SetDate(DateTime dt)
        {
            _DateTaken = dt;
        }

        internal void SetMagneticVariation(double val, DirectionType dir)
        {
            _MagneticVariation = val;
            _MagneticDirection = dir;
        }

        internal void SetSelectionModeAnd3dFix(SelectionMode selectionMode, int threeDFix)
        {
            _SelectionMode = selectionMode;
            _threeDFix = threeDFix;
        }


        internal void SetSatellitePRN(int idx, int prnNumber)
        {
            _PRNForFix[idx] = prnNumber;
        }

        internal void SetSatelliteElevation(int idx, int val)
        {
            _Elevation[idx] = val;
        }

        internal void SetSatelliteAzimuth(int idx, int val)
        {
            _Azimuth[idx] = val;
        }

        internal void SetSatelliteSNR(int idx, int val)
        {
            _SNR[idx] = val;
        }
        internal void SetDilutionOfPrecision(double val)
        {
            _DilutionOfPrecision = val;
        }

        internal void SetVerticalDilution(double val)
        {
            _VerticalDilution = val;
        }

        internal void SetSentenceCount(int sentCount)
        {
            _SentenceCount = sentCount;
        }

        internal void SetSentenceNumber(int sentNum)
        {
            _SentenceNumber = sentNum;
        }


        internal void SetElevation(int idx, int val)
        {
            _Elevation[idx] = val;
        }

        internal void SetAzimuth(int idx, int val)
        {
            _Azimuth[idx] = val;
        }

        internal void SetSNR(int idx, int val)
        {
            _SNR[idx] = val;
        }

        internal void ClearData()
        {
            Init();
        }


        public override string ToString()
        {
            String ret = "";
            ret += MessageTypeToken.MessageTypeText[(int)MessageType] + ":\n";
            ret += "Time Taken: " + TimeTaken.ToString() + "\n";
            ret += "Latitude: " + LatitudeDegrees + " Degrees " + LatitudeMinutes + " Minutes " + DirectionTypeToken.DirectionTypeText[(int)LatitudeDirection] + "\n";
            ret += "Longitude: " + LongitudeDegrees + " Degrees " + LongitudeMinutes + " Minutes " + DirectionTypeToken.DirectionTypeText[(int)LongitudeDirection] + "\n";
            ret += LatitudeDecimalDegrees + ", " + LongitudeDecimalDegrees;
            return ret;
        }



    }
}
